/****************************************************************
 ** Product  :   HP Subscriber Network Application Policy
 ** Module   :   gr-manager
 ** Date: Apr 10, 2015               
 ** Author: Huang xiaoji
 ** (C) Copyright 2015, Hewlett-Packard Company, All Rights Reserved.
 ** This software is the proprietary information of HP, Inc.  
 ** Use is subject to license terms.
 *****************************************************************
 ** Description:   
 **     Export both structure and data from Mysql
 **    
 ****************************************************************/
package com.hp.snap.gr.action.impl;

import com.hp.snap.gr.exception.ActionException;
import com.hp.snap.gr.model.jaxb.ActionType;
import com.hp.snap.gr.model.jaxb.ExportMySqlDBActionType;
import com.hp.snap.gr.utils.CmdUtils;
import com.hp.snap.gr.utils.Constants;
import com.hp.snap.gr.utils.GRMConfigManager;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * 
 * Export both structure and data from Mysql by executing the mysqldump command to a specified directory. Export tables
 * can be specified in the action configuration parameters. The tables filter support wildcard "%".
 * 
 * The action configuration contains some parameters: outputDirectory, dbHost, dbPort, dbName, dbUser, dbPassword and tableList.
 * outputDirectory: The export destination directory
 * dbHost: Mysql database host name
 * dbPort: Mysql database port number
 * dbName: Mysql database instance name
 * dbUser: Mysql database username
 * dbPassword: Mysql database password
 * tableList: table name filter, '%' means any matches and multiple filter splited by ','
 * 
 * <P>
 * Version: 3.3 <br>
 * Author: Huang xiaoji Date: Apr 10, 2015
 * 
 * </P>
 * 
 **/
public class ExportMySqlDBActionHandler extends AbstractActionHandler {
    private static final Logger logger = LoggerFactory.getLogger(ExportMySqlDBActionHandler.class);

    @Override
    public void execute(ActionType action, Map<String, Object> actionPlanInputs, Map<String, Object> actionPlanOutputs) throws ActionException {
        if (action instanceof ExportMySqlDBActionType) {
            ExportMySqlDBActionType actionType = (ExportMySqlDBActionType) action;

            Set<String> tablefilters = new HashSet<String>();
            if (StringUtils.isNotEmpty(actionType.getTableList()) && !actionType.getTableList().equalsIgnoreCase("null")) {
                String[] vars = actionType.getTableList().split("\\s*,\\s*");
                for (String var : vars) {
                    if (var.equals("%")) {
                        if (logger.isTraceEnabled()) {
                            logger.trace("table filter condition has an all table filter, skip filter tables. condition: {}", actionType.getTableList());
                        }
                        tablefilters.clear();
                        break;
                    } else {
                        tablefilters.add(var);
                    }
                }
            }
            StringBuffer sb = new StringBuffer(GRMConfigManager.getEIUMHome());
            sb.append(File.separator).append("mysql").append(File.separator).append("bin")
                    .append(File.separator).append("mysqldump -h").append(actionType.getDbHost())
                    .append(" -P").append(actionType.getDbPort() == null ? 3306 : actionType.getDbPort())
                    .append(" -u").append(actionType.getDbUser()).append(" -p")
                    .append(actionType.getDbPassword() == null ? "" : actionType.getDbPassword());

            String tablecondition = "";
            if (!tablefilters.isEmpty()) {
                String cleanenv = "cat /dev/null > " +
                        Constants.USER_GR_TEMP + File.separator + "tables.txt && cat /dev/null > " +
                        Constants.USER_GR_TEMP + File.separator + "ntables.txt && ";
                for (String filter : tablefilters) {
                    StringBuffer cmd = new StringBuffer();
                    String outputfile = "tables.txt";
                    cmd.append(GRMConfigManager.getEIUMHome()).append(File.separator)
                            .append("mysql").append(File.separator).append("bin")
                            .append(File.separator).append("mysql -h").append(actionType.getDbHost())
                            .append(" -P").append(actionType.getDbPort() == null ? 3306 : actionType.getDbPort())
                            .append(" -u").append(actionType.getDbUser()).append(" -p")
                            .append(actionType.getDbPassword() == null ? "" : actionType.getDbPassword())
                            .append(" -N -e \"select table_name from INFORMATION_SCHEMA.TABLES where table_schema = '")
                            .append(actionType.getDbName()).append("' and table_name ");
                    if (filter.startsWith("!")) {
                        cmd.append("like '").append(filter.substring(1));
                        outputfile = "ntables.txt";
                    } else {
                        cmd.append("like '").append(filter);
                    }
                    cmd.append("'\" >> ");

                    cmd.append(Constants.USER_GR_TEMP).append(File.separator).append(outputfile);

                    try {
                        int rs = CmdUtils.runShellScript((cleanenv != null ? cleanenv : "") + cmd.toString());
                        cleanenv = null;
                        if (rs != 0) {
                            if (logger.isTraceEnabled()) {
                                logger.trace("command {} executed return {}", cmd, rs);
                            }
                            throw new ActionException("command executed failed with exit code " + rs);
                        }
                    } catch (Exception e) {
                        logger.error(e.getMessage(), e);
                        throw new ActionException("execute command failed", e);
                    }
                }
                tablecondition = "`grep -vf " + Constants.USER_GR_TEMP + File.separator + "ntables.txt " +
                        Constants.USER_GR_TEMP + File.separator + "tables.txt`";
            }
            sb.append(" ").append(actionType.getDbName()).append(" ").append(tablecondition).append(" > ")
                    .append(actionType.getOutputDirectory() == null ? Constants.USER_GR_WORK + File.separator + "exportTarget" : actionType.getOutputDirectory())
                    .append(File.separator).append(actionType.getDbName()).append(".sql");

            try {
                int rs = CmdUtils.runShellScript(sb.toString());
                if (rs != 0) {
                    if (logger.isTraceEnabled()) {
                        logger.trace("command {} executed return {}", CmdUtils.printableCommand(sb.toString()), rs);
                    }
                    throw new ActionException("command executed failed with exit code " + rs);
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
                throw new ActionException("export mysql data failed", e);
            }
        }
    }
}
